Release 10.1A: OpenEdge Development:
Progress Dynamics Advanced Development
Identifying the level of an attribute value
Because the attribute value can be associated with any of three other tables (
gsc_object_type,ryc_smartobject, orryc_object_instance), it is necessary to identify which of the tables the value relates to. This tells us whether this is:The
ryc_attribute_valuetable contains anobject_type_objobject ID field, asmartobject_objobject ID, and anobject_instance_objobject ID. There is also an object ID field for thecontainer_smartobject_objif this value is for anobject_instance. Figure 8–4 is a diagram from the database model and illustrates how these fields relate theattribute_valueto theobject_type,smartobject, andobject_instancetables.Figure 8–4: Attribute value and table relationships
![]()
The following sections describe the different ways these fields can be used:
Defining attributes at the object type level
When the framework creates entries for attributes of an object type, the
object_type_objpoints to the objectTypeclass, and the SmartObject and instance object IDs are set to 0.To illustrate, Figure 8–5 shows an example diagram for the
NavigationSourceEventsattribute, defined for theQueryclass. AQueryobject, such as an SDO, subscribes to various events in itsNavigation-Source, and this attribute lists those events. These are defined at the class level and normally not changed by individual objects built using the class. So we can expect that there will be a singleryc_attribute_valuerecord in the Repository database for this attribute for theQueryclass, but no other records for specific SDOs in the application. Figure 8–5 shows the relationships for theattribute_valuerecord in this case.Figure 8–5: NavigationSourceEvents attribute
![]()
Here you see that only the object type relationship is defined for attribute values that are default values for a class.
Defining attribute values at the object master level
When the framework creates entries in the table for an object master, it populates the
object_type_objfield to avoid having 0 in the key. It also sets thesmartobject_objto point to theryc_smartobjectrecord that defines the object.To illustrate this case, Figure 8–6 shows the relationships for the
MinHeightattribute of the dynamic viewercustomerviewv. This attribute sets an object’s initial height and is defined when the object is created. Because viewers come in all different sizes, this attribute is defined at the master level, along with theMinWidthattribute, to define the size of the viewer. You can see this attribute in the dynamic property sheet for the viewer when you edit it in the AppBuilder.Figure 8–6: Attributes defined at the object master level
![]()
Figure 8–7 shows how the
attribute_valuerecord is related to other records.Figure 8–7: Relationships of attribute value records to other records
![]()
In this illustration, you can see that the SmartObject relationship is defined for the
attribute_valuebecause it is a value for a particular SmartObject. Because this is the master for the object, there is no instance or container relationship.Attribute values defined at the object instance level
When the framework creates attributes for an object instance, it populates the
object_type_objand thesmartobject_objfields, and also sets theobject_instance_objfield to point to theryc_object_instancerecord that defines the instance, as well as thecontainer_smartobject_objfield, which points to the container’sryc_smartobjectrecord.To illustrate this case, we can extend the second example to show another attribute of the same dynamic viewer. In this case, we pick an attribute that can be changed at the instance level, such as
DisableOnInit. You can change this from its default value ofNotoYesin the dynamic property sheet, as shown in Figure 8–8.Figure 8–8: Attributes defined at the object instance level
![]()
If you do this in the Container Builder, when you are building a window such as the
oemaintwinexample, you are changing the attribute value just for that single instance of the viewer, as used in that window. The framework creates anattribute_valuerecord to represent this overridden value and connects it to the object type, the viewer SmartObject, the object instance record for the viewer instance, and the SmartObject record for the container window.Figure 8–9 shows the relationships for the instance
attribute_value.Figure 8–9: Instance attribute value relationships
![]()
The
container_smartobject_objpoints to the SmartObject for the window, and theobject_instance_objpoints to the instance of the viewer created for this window. When you place the viewer into the window in the Container Builder, you are creating anobject_instancefor it, which can have its own instance name and its own attribute values, as shown in Figure 8–10.Figure 8–10: Object instances in the container builder window
![]()
All of this means that there are several different combinations of object ID pointers that framework code must check for to determine the level of an attribute value and what object it is defined for. To assist in this, another object ID field holds the meaningful identifier for the value, so that code can look at a single field to determine what the significant key is. This field is called the
Note: Be careful when looking for attributes associated with anprimary_smartobject_obj. This field contains the value of thecontainer_smartobject_objif that is not 0; otherwise thesmartobject_objif that is not 0; otherwise 0. It is used as the replication key field when writing replication triggers to cascade changes to the version database, as the replication triggers could not handle the use of alternative fields (for example,container_smartobject_objorsmartobject_obj). The update of this field is done in the write trigger for the table.object_type. Make sure that you look for the specificobject_typeand 0 values for the SmartObject andobject_instanceobject ID fields.This might all sound complicated, but the rules that determine which fields are used are fairly straightforward. We can summarize all this with some code samples in the following sections.
Code examples for an attribute value at the class level
If an attribute value is defined for an object type or class, then the
object_type_objis defined and points to theobject_typerecord. The other object IDs, for SmartObject, instance, and container, are not defined (therefore 0), because the value is not associated with a specific object. You can determine all the default attribute values for a class by retrieving theattribute_valuerecords for whichsmartobject_obj,object_instance_obj, andcontainer_smartobject_objare all 0.The next example shows a simple code block that locates all the object type records for the
NavigationSourceEventsattribute. The code retrieves only records where thesmartobject_objis 0. (If this is the case, thenobject_instance_objandcontainer_smartobject_objare also 0.) This locates the attribute values defined at the class level, as shown:
This result in Figure 8–11 shows that there are two classes that define this attribute.
Figure 8–11: Class level attribute value
![]()
We have already discussed the
Queryclass. TheContainerclass uses this attribute because a container can be a pass-through object for aNavigationlink coming in from outside the container. We can see that both classes define the same initial value for the attribute. Because it’s aCHARACTERattribute, the value is stored in thecharacter_valuefield.To confirm that this attribute does not change below the class level, you can leave out the
WHEREclause qualifierAND smartobject_obj = 0. For example:
When you run this, the result is the same: only the two records show up. So, no master SmartObjects override this default value.
Code examples for an attribute value at the master level
If an attribute value is defined for an object master, then the significant pointer is the
smartobject_obj, which joins the record to the SmartObject record for the master object. Theobject_typeis also filled in the previous example.Another simple code block illustrates this relationship. The code looks for any
attribute_valuefor theMinHeightattribute that has a SmartObject object ID. These all join to a SmartObject master. We only want to see those values that are defined for the master and not for one of its instances, so we also include the qualifierobject_instance_obj = 0. For example:
This is the result of the request. Figure 8–12 shows the
customerviewvviewer among the objects with an assignedMinHeightvalue.Figure 8–12: Objects with assigned minimum height values
![]()
To find out which object types have a
MinHeightdefined for the class itself, look for object types where thesmartobject_objis equal to 0. For example:
There are in fact a few classes that define an initial value for the
MinHeight, as shown in Figure 8–13.Figure 8–13: Classes with defined initial values for MinHeight
![]()
In this example, the default height for a dynamic browser is 6.67 rows. Because the browser is a resizable object, this value applies initially to all dynamic browsers, unless you set it otherwise for the master or for an instance of the master in a window. By contrast, the dynamic viewer class does not have a default for
MinHeight, because the height of the viewer is always determined by the layout of the fields it contains.Code example for an attribute value at the instance level
If an attribute value is defined for an object instance, then there are really three significant pointers. As for the master attribute, the
smartobject_objjoins theattribute_valuerecord to the master SmartObject. In addition, theobject_instance_objjoins the record to theobject_instanceof the SmartObject it’s defined for. Because the instance is always defined in the context of a particular container, thecontainer_smartobject_objis also defined and points to the SmartObject record of the container window. Again, for completeness, theobject_type_objis also filled in.The following code is an example of this relationship using the
DisableOnInitattribute. This block of code locates allattribute_valuerecords where theDisableOnInitattribute has been set toYESat theobject_instancelevel.The code follows the join to locate the master SmartObject record for the value. It also follows the join to the
object_instancefor the value, from which it displays the layout position. Then it follows the join to the SmartObject record for the container. Because there are two different SmartObjectss the attribute value joins to, the master and the container, the code needs a second buffer for the container, as shown:
When you run this block of code, you see the three viewers in the
oemaintwintest window shown in Figure 8–14. These are all disabled on initialization. (Note that theOrderLineviewer and theOrderviewer have the same layout position because they are on different pages.)Figure 8–14: DisableOnInit properties for oemaintwin
![]()
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |